#    Dexter WIKI a simple wiki for GAE.>
#    Copyright (C) 2010  kishore@acesurf.org
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

import collections
import cgi
import os
import datetime
import re
import urllib

from google.appengine.api import mail
from google.appengine.ext.webapp import template
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
from model import Category,Page,Comment


admin_mail= "The Acesurf Foundation <Collaborate@acesurf.org>"
group_mail = "Acesurf Group <all@acesurf.org>"

# utilities
def sendMail(email_id,subject,body):
    if mail.is_email_valid(email_id):
        mail.send_mail(admin_mail, email_id, subject, body)  
        
def sendPageInfoMail(page):    
    subject = "Acesurf Wiki Info Mail "
    body = """

Dear Acesurf Group, 

    Acesurf Wiki %s is created/edited by %s 
Visit: wiki.acesurf.org/pages/%s to view it


Cheers,
The Acesurf Foundation
""" % (page.name,page.user.email(), page.name)
    sendMail(group_mail, subject, body)     

# BaserequestHandler
class BaseRequestHandler(webapp.RequestHandler):
    def generate(self, template_name, template_values={}):
        recentPages = db.GqlQuery("SELECT * FROM Page ORDER BY edited DESC LIMIT 5") 
        recentComments = db.GqlQuery("SELECT * FROM Comment ORDER BY created DESC LIMIT 5")              
        categories = db.GqlQuery("SELECT * FROM Category")   
        values = {
          'recentPages':recentPages,
          'recentComments':recentComments,
          'categories':categories,
          'request': self.request,
          'user': users.GetCurrentUser(),
          'isAdmin':users.is_current_user_admin(),
          'login_url': users.CreateLoginURL(self.request.uri),
          'logout_url': users.CreateLogoutURL(self.request.uri),
          'application_name': 'Acesurf Wiki',
        }
        values.update(template_values)
        directory = os.path.dirname(__file__)
        path = os.path.join(directory, os.path.join('templates', template_name))
        self.response.out.write(template.render(path, values,debug=True))


class Wiki(BaseRequestHandler):
    def get(self,page_name):
        values = {} 
        mode = self.request.get("mode",default_value="view")
        if not page_name:
            page_name = 'MainPage'
        page_name = urllib.unquote(page_name)              
                        
        show_page = db.GqlQuery("SELECT * FROM Page WHERE name = :1",page_name)
        if show_page.count()==0:
            mode = 'edit'
            values.update({'page_name':page_name})
        else:
            values.update({'show_page':show_page.get(),'page_name':show_page.get().name})
        if mode=="edit":            
            user = users.get_current_user()
            if not user:
                self.redirect(users.CreateLoginURL(self.request.uri))
        self.generate(mode+'.html',values)
        
class MainPage(BaseRequestHandler):
    def get(self):
        self.redirect('/pages/')

class SavePage(BaseRequestHandler):
    def post(self):
        
        #User authentication
        user = users.get_current_user()
        if not user:
            self.redirect(users.CreateLoginURL(self.request.uri))           
        category_name = self.request.get("category_name", default_value="default")
        category_name = urllib.unquote(category_name)    
        category_list = db.GqlQuery("SELECT * FROM Category where name = :1",category_name)
        if category_list.count()==0:
            category = Category(name=category_name)
            category.put()
        else:
            category = category_list.get()
            
        # Get the Page Details
        page_name = self.request.get("page_name")
        page_name = urllib.unquote(page_name) 
        if page_name:
            content = self.request.get("content")
            page_list =  db.GqlQuery("SELECT * FROM Page where name = :1",page_name)
            if page_list.count()==0:
                page = Page(name=page_name)
            else:
                page = page_list.get() 
            page.content = content
            page.category = category
            page.edited = datetime.datetime.now()
            page.user = user
            page.put()
            sendPageInfoMail(page)
            self.redirect('/pages/'+page_name)
        else:
            values={'message':'Page not specified'}
            self.generate('message.html',values)       

# Creating the category
class CreateCategory(BaseRequestHandler):
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.CreateLoginURL(self.request.uri))
        if users.is_current_user_admin(): 
            page_name = self.request.get("page_name")
            page_name = urllib.unquote(page_name)
            values={}
            if page_name:
                values={'redirect':page_name}
            self.generate('createCategory.html',values)
        else:
            values={'message':'No permissions to Create Category'}
            self.generate('message.html',values) 
                        
    def post(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.CreateLoginURL(self.request.uri)) 
        if users.is_current_user_admin():            
            page_name = self.request.get("page_name")
            page_name = urllib.unquote(page_name)
            category_name = self.request.get("category_name", default_value="default")
            category_name = urllib.unquote(category_name)  
            category_list = db.GqlQuery("SELECT * FROM Category where name = :1",category_name)
            if category_list.count()==0:
                category = Category(name=category_name)
                category.put()
            if page_name:
                self.redirect('/pages/'+page_name+'?mode=edit')
            else:
                self.redirect('/')
        else:
            values={'message':'No permissions to Create Category'}
            self.generate('message.html',values) 
        

# getting pages list        
class GetPages(BaseRequestHandler):
    def get(self):
        category_name = self.request.get("category_name", default_value="default")
        category_name = urllib.unquote(category_name)  
        category_list = db.GqlQuery("SELECT * FROM Category where name = :1",category_name)
        self.generate('getPages.html',{'pages':category_list.get().pages})

# remove Page
class RemovePage(BaseRequestHandler):
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.CreateLoginURL(self.request.uri))            
        page_name = self.request.get("page_name")
        page_name = urllib.unquote(page_name)
        page_list =  db.GqlQuery("SELECT * FROM Page where name = :1",page_name)
        if page_list.count()==0:
            values={'message':'No Page with name '+page_name}
        else:
            page = page_list.get() 
            if users.is_current_user_admin():
                values={'message':'Page '+page_name+' Deleted'}
                for comment in page.comments:
                    comment.delete()
                page.delete()
            else:
                values={'message':'No permissions to delete'}
        self.generate('message.html',values)    

# Remove Category
class RemoveCategory(BaseRequestHandler):
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.CreateLoginURL(self.request.uri))            
        category_name = self.request.get("category_name")
        category_name = urllib.unquote(category_name)  
        category_list =  db.GqlQuery("SELECT * FROM Category where name = :1",category_name)
        if users.is_current_user_admin():
            if  category_list.count()!=0:
                category = category_list.get()
                for page in category.pages:
                    for comment in page.comments:
                        comment.delete()
                    page.delete()
                category.delete()
                values={'message':'Category '+category_name+' deleted'}
            else:
                values={'message':'No Category with name '+category_name}
        else:
            values={'message':'No permissions to delete'}
        
        self.generate('message.html',values)


# Create new Page
class AddComment(BaseRequestHandler):
    def post(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.CreateLoginURL(self.request.uri)) 
        page_name = urllib.unquote(self.request.get("page_name",default_value="MainPage"))
        page_list =  db.GqlQuery("SELECT * FROM Page where name = :1",page_name)
        if page_list.count()==0:
            values={'message':'No Page with name '+page_name}
            self.generate('message.html',values)            
        else:
            page = page_list.get()
            comment= Comment()
            comment.content = self.request.get("content",default_value="MainPage")
            if len(comment.content) != 0:                
                comment.user = users.get_current_user()
                comment.page = page
                comment.created = datetime.datetime.now()
                comment.put()            
                self.redirect('/pages/'+page_name)
            else:
                values={'message':'comment is empty'}
                self.generate('message.html',values)

class RemoveComment(BaseRequestHandler):
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.CreateLoginURL(self.request.uri))
        page_name = urllib.unquote(self.request.get("page_name",default_value="MainPage"))
        page_list =  db.GqlQuery("SELECT * FROM Page where name = :1",page_name)
        if page_list.count()==0:
            values={'message':'No Page with name '+page_name}
            self.generate('message.html',values)            
        else:
            page = page_list.get()
            if page.user==users.get_current_user():
                comment_id = urllib.unquote(self.request.get("comment_id"))
                comment_list = db.GqlQuery("SELECT * FROM Comment where id = :1",comment_id)
                if comment_list.count() != 0:
                    comment = comment_list.get()
                    comment.delete()
                    self.redirect("/pages/"+page_name)
                else:
                    values={'message':'No Comment'}
                    self.generate('message.html',values)                     
            else:
                values={'message':'No Permissions'}
                self.generate('message.html',values) 
                
                


# Create new Page
class NewPage(BaseRequestHandler):
    def get(self):
        user = users.get_current_user()
        if not user:
            self.redirect(users.CreateLoginURL(self.request.uri)) 
        self.generate('edit.html',{})      

# Error page
class NotFound(BaseRequestHandler):
    def get(self,page_name):
        self.generate('error.html',{'resource':page_name})            
        
application = webapp.WSGIApplication(
                                     [('/',MainPage),
                                      ('/newPage',NewPage),
                                      ('/savePage',SavePage),
                                      ('/removePage',RemovePage),
                                      ('/createCategory',CreateCategory),
                                      ('/removeCategory',RemoveCategory),
                                      ('/getPages',GetPages),
                                      ('/addComment',AddComment),
                                      ('/pages/(.*)', Wiki),
                                      ('/(.*)',NotFound)],
                                     debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()
